package com.gitee.sergius.exceltool.export;

import com.gitee.sergius.exceltool.exception.ExcelException;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.util.CellRangeAddress;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.*;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <p>描述：导出到excel文件工具
 *
 * @author shawn yang
 * @version 1.00
 */
public class ExcelExporter {

    /**
     * 设置列宽，最小5，最大500，不设置默认为15
     * @param columnWidth 列宽
     * @return 实例化对象
     */
    public ExcelExporter columnWidth(int columnWidth){
        if(columnWidth > this.SMALLEST_COLUMN_WIDTH &&
                columnWidth < this.BIGGEST_COLUMN_WIDTH){
            COLUMN_WIDTH = columnWidth;
        }
        return this;
    }

    /**
     * 设置日期类型数据展示格式，不设置默认为"2010-11-12 12:10:10"
     * @param dataFormat 日期格式
     * @return 实例化对象
     */
    public ExcelExporter dataFormat(String dataFormat) {
        DATE_FORMAT = dataFormat;
        return this;
    }

    /**
     * 设置数据写入起始行
     * @param row 行号，从0开始
     * @return 实例化对象
     */
    public ExcelExporter startRow(int row){
        if(row >= 0){
            START_ROW = row;
        }
        return this;
    }

    /**
     * 设置数据写入起始列
     * @param column 列号，从0开始
     * @return 实例化对象
     */
    public ExcelExporter startColumn(int column){
        if(column >=0 ){
            START_COLUMN = column;
        }
        return this;
    }

    /**
     * 设置sheet页名称
     * @param sheetTitle sheet页名称
     * @return 实例化对象
     */
    public ExcelExporter sheetTitle(String sheetTitle){
        if(sheetTitle != null && !"".equals(sheetTitle.trim())){
            this.SHEET_TITLE = sheetTitle.trim();
        }
        return this;
    }

    /**
     * 设置列名称
     * @param headers 列名称数组
     * @return 实例化对象
     */
    public ExcelExporter headers(String... headers){
        if(headers != null && headers.length > 0){
            this.HEADERS = headers;
        }
        return this;
    }

    /**
     * 设置不导出的域，形式为“类名.属性名”，例如：User.bizType，
     *                需要导出的字段必须要有get方法否则抛出NoSuchMethodException
     * @param fields 需要过滤掉不导出的域的集合
     * @return 实例化对象
     */
    public ExcelExporter excludedFields(String... fields){
        if(fields != null && fields.length > 0){
            this.EXCLUDED_FIELDS = new HashSet<>();
            for(String field : fields){
                this.EXCLUDED_FIELDS.add(field);
            }
        }
        return this;
    }

    /**
     * 数据库导出的某列数据如果需要做转换,可以用此参数,
     * <p>
     * 例如需要将EsService中的serviceType字段根据值来做判断，可以如下操作:
     * <blockquote><pre>
     *      Map<String,HashMap<String,Object>> fieldReflectMap = new HashMap<String,HashMap<String,Object>>();
     *      HashMap<String,String> switchMap = new HashMap<String,String>();
     *      switchMap.put("salebefore","售前");//如果该字段的值为“salebefore”，将被映射成“售前”
     *      switchMap.put("saleafter", "售后");
     *      switchMap.put("delivery", "物流");
     *      switchMap.put("suggustion", "投诉建议");
     *      switchMap.put("others", "其他");
     *      fieldReflectMap.put("EsService.serviceType",switchMap);//key采用“类名.属性名”的方式
     * </pre></blockquote><p>
     * 如果父类里面有list，list需要映射,可以将list中元素的类按照上面添加到map即可
     *
     * @param fieldReflectMap 映射表
     * @return
     */
    public ExcelExporter fieldReflectMap(Map<String, HashMap<String, Object>> fieldReflectMap){
        if(fieldReflectMap != null && !fieldReflectMap.isEmpty()){
            this.FIELD_REFLECT_MAP = fieldReflectMap;
        }
        return this;
    }


    /**
     * 生成workbook实体
     */
    private Map<String, Field[]> listFieldMap = new HashMap<>();
    public <T> ExcelExporter produce(List<T> dataset) throws ExcelException{
        listFieldMap = getListFieldMap(dataset);

        this.WORKBOOK = new HSSFWorkbook();

        HSSFSheet sheet = this.WORKBOOK.createSheet(this.SHEET_TITLE);
        sheet.setDefaultColumnWidth(this.COLUMN_WIDTH);

        int index = this.START_ROW;
        HSSFRow row = null;
        if (this.HEADERS != null && this.HEADERS.length > 0) {
            // 产生表格标题行
            row = sheet.createRow(index);
            HSSFCellStyle headerStyle = getHeaderStyle();
            for (int i = 0; i < this.HEADERS.length; i++) {
                HSSFCell cell = row.createCell(i + START_COLUMN);
                cell.setCellStyle(headerStyle);
                HSSFRichTextString text = new HSSFRichTextString(this.HEADERS[i]);
                cell.setCellValue(text);
            }
            index++;
        }


        // 遍历集合数据，产生数据行
        Iterator<T> it = dataset.iterator();
        int mergeRow = 1;
        HSSFCellStyle contentStyle = setContentStyle();
        while (it.hasNext()) {
            T t = (T) it.next();
            mergeRow = getMergeRow(t);
            for (int i = 0; i < mergeRow; i++) {
                row = sheet.createRow(index + i);
            }
            Field[] fields = fieldFilterFun(t.getClass());
            // index起始行，fileds所有的列信息,col来定义列
            for (int i = 0, col = START_COLUMN; i < fields.length; i++) {
                Field field = fields[i];
                String fieldName = field.getName();
                String getMethodName = "get"
                        + fieldName.substring(0, 1).toUpperCase()
                        + fieldName.substring(1);
                Class<? extends Object> tCls = t.getClass();
                String datasetClassName = tCls.getSimpleName();
                Method getMethod ;
                Object value ;
                try{
                    getMethod = tCls.getMethod(getMethodName, new Class[]{});
                    value = getMethod.invoke(t, new Object[]{});
                }catch(NoSuchMethodException e){
                    throw new ExcelException("Method "+getMethodName+" in class "+tCls.getSimpleName()+" is missed!");
                }catch(Exception e){
                    throw new ExcelException("Method "+getMethodName+" in class "+tCls.getSimpleName()+" invoked with error!");
                }
                if (value instanceof Date) {
                    Date date = (Date) value;
                    String srcValue = formatDate(date);
                    HashMap<String, Object> reflectMap = null;
                    if (this.FIELD_REFLECT_MAP != null) {
                        reflectMap = this.FIELD_REFLECT_MAP.get(datasetClassName
                                + "." + fieldName);
                    }
                    CellRangeAddress cra = new CellRangeAddress(index, index
                            + mergeRow - 1, col, col);
                    sheet.addMergedRegion(cra);
                    for (int rowIn = index; rowIn <= index + mergeRow - 1; rowIn++) {
                        Cell cell_1 = sheet.getRow(rowIn).createCell(col);
                        cell_1.setCellStyle(contentStyle);
                    }
                    Cell cell_1 = sheet.getRow(index).getCell(col);
                    // cell_1.setCellStyle(contentStyle);
                    if (reflectMap != null) {
                        Object textObject = fieldReflectFun(srcValue,
                                reflectMap);
                        if (textObject instanceof Double) {

                            cell_1.setCellType(Cell.CELL_TYPE_NUMERIC);
                            cell_1.setCellValue(((Double) textObject)
                                    .doubleValue());
                        } else {
                            cell_1.setCellType(Cell.CELL_TYPE_STRING);
                            cell_1.setCellValue(textObject.toString());
                        }
                    } else {
                        cell_1.setCellType(Cell.CELL_TYPE_STRING);
                        cell_1.setCellValue(srcValue);
                    }
                    col++;
                } else if (value instanceof Integer || value instanceof Long
                        || value instanceof Short || value instanceof Float
                        || value instanceof Double
                        || value instanceof BigDecimal) {
                    String srcValue = value.toString();
                    HashMap<String, Object> reflectMap = null;
                    if (this.FIELD_REFLECT_MAP != null) {
                        reflectMap = this.FIELD_REFLECT_MAP.get(datasetClassName
                                + "." + fieldName);
                    }
                    CellRangeAddress cra = new CellRangeAddress(index, index
                            + mergeRow - 1, col, col);
                    sheet.addMergedRegion(cra);
                    for (int rowIn = index; rowIn <= index + mergeRow - 1; rowIn++) {
                        Cell cell_1 = sheet.getRow(rowIn).createCell(col);
                        cell_1.setCellStyle(contentStyle);
                    }
                    Cell cell_1 = sheet.getRow(index).getCell(col);
                    // cell_1.setCellStyle(contentStyle);

                    if (reflectMap != null) {
                        Object textObject = fieldReflectFun(srcValue,
                                reflectMap);
                        if (textObject instanceof Double) {

                            cell_1.setCellType(Cell.CELL_TYPE_NUMERIC);
                            cell_1.setCellValue(((Double) textObject)
                                    .doubleValue());
                        } else {
                            cell_1.setCellType(Cell.CELL_TYPE_STRING);
                            cell_1.setCellValue(textObject.toString());
                        }
                    } else {
                        cell_1.setCellType(Cell.CELL_TYPE_NUMERIC);
                        cell_1.setCellValue(Double.parseDouble(srcValue));
                    }
                    col++;
                } else if (value instanceof List) {
                    // col列起始，index行起始，
                    @SuppressWarnings("rawtypes")
                    List subList = (List) value;
                    Field[] listFields = listFieldMap.get(fieldName);
                    int len = subList.size();
                    if (len == 0) {// 如果对应的子list为空时，也要绘制一行相应的格式进去
                        int thisCol = col;
                        for (int subListFieldIndex = 0; subListFieldIndex < listFields.length; subListFieldIndex++) {
                            Cell scell_1 = sheet.getRow(index).createCell(
                                    thisCol + subListFieldIndex);
                            scell_1.setCellStyle(contentStyle);
                        }
                    } else {

                        for (int subListIndex = 0; subListIndex < len; subListIndex++) {
                            int thisCol = col;
                            Object o = subList.get(subListIndex);
                            for (int subListFieldIndex = 0; subListFieldIndex < listFields.length; subListFieldIndex++) {
                                Field sfield = listFields[subListFieldIndex];
                                String sfieldName = sfield.getName();
                                String sgetMethodName = "get"
                                        + sfieldName.substring(0, 1)
                                        .toUpperCase()
                                        + sfieldName.substring(1);
                                Class<? extends Object> oCls = o.getClass();
                                String subListClassName = oCls.getSimpleName();

                                Method sgetMethod ;
                                Object svalue ;
                                try{
                                    sgetMethod = oCls.getMethod(sgetMethodName, new Class[]{});
                                    svalue = sgetMethod.invoke(o, new Object[]{});
                                }catch(NoSuchMethodException e){
                                    throw new ExcelException("Method "+sgetMethodName+" in class "+subListClassName+" is missed!");
                                }catch(Exception e){
                                    throw new ExcelException("Method "+sgetMethodName+" in class "+subListClassName+" invoked with error!");
                                }


                                HashMap<String, Object> sreflectMap = null;
                                if (this.FIELD_REFLECT_MAP != null) {
                                    sreflectMap = this.FIELD_REFLECT_MAP
                                            .get(subListClassName + "."
                                                    + sfieldName);
                                }
                                Cell scell_1 = sheet.getRow(
                                        index + subListIndex).createCell(
                                        thisCol + subListFieldIndex);
                                scell_1.setCellStyle(contentStyle);
                                if (svalue instanceof Date) {// 日期型
                                    Date sdate = (Date) svalue;
                                    String ssrcValue = formatDate(sdate);
                                    if (sreflectMap != null) {
                                        Object stextObject = fieldReflectFun(
                                                ssrcValue, sreflectMap);
                                        if (stextObject instanceof Double) {
                                            scell_1.setCellType(Cell.CELL_TYPE_NUMERIC);
                                            scell_1.setCellValue(((Double) stextObject)
                                                    .doubleValue());
                                        } else {
                                            scell_1.setCellType(Cell.CELL_TYPE_STRING);
                                            scell_1.setCellValue(stextObject
                                                    .toString());
                                        }
                                    } else {
                                        scell_1.setCellType(Cell.CELL_TYPE_STRING);
                                        scell_1.setCellValue(ssrcValue);
                                    }
                                } else if (svalue instanceof Integer
                                        || svalue instanceof Long
                                        || value instanceof Short
                                        || svalue instanceof Float
                                        || svalue instanceof Double
                                        || value instanceof BigDecimal) {// 数值型
                                    String ssrcValue = svalue.toString();
                                    if (sreflectMap != null) {
                                        Object stextObject = fieldReflectFun(
                                                ssrcValue, sreflectMap);
                                        if (stextObject instanceof Double) {

                                            scell_1.setCellType(Cell.CELL_TYPE_NUMERIC);
                                            scell_1.setCellValue(((Double) stextObject)
                                                    .doubleValue());
                                        } else {
                                            scell_1.setCellType(Cell.CELL_TYPE_STRING);
                                            scell_1.setCellValue(stextObject
                                                    .toString());
                                        }
                                    } else {
                                        scell_1.setCellType(Cell.CELL_TYPE_NUMERIC);
                                        scell_1.setCellValue(Double
                                                .parseDouble(ssrcValue));
                                    }
                                } else {// 字符型
                                    String ssrcValue = "";
                                    if (svalue != null) {
                                        ssrcValue = svalue.toString();
                                    }
                                    if (sreflectMap != null) {
                                        Object stextObject = fieldReflectFun(
                                                ssrcValue, sreflectMap);
                                        if (stextObject instanceof Double) {
                                            scell_1.setCellType(Cell.CELL_TYPE_NUMERIC);
                                            scell_1.setCellValue(((Double) stextObject)
                                                    .doubleValue());
                                        } else {
                                            scell_1.setCellType(Cell.CELL_TYPE_STRING);
                                            scell_1.setCellValue(stextObject
                                                    .toString());
                                        }
                                    } else {
                                        scell_1.setCellType(Cell.CELL_TYPE_STRING);
                                        scell_1.setCellValue(ssrcValue);
                                    }
                                }
                            }
                        }
                    }
                    col += listFields.length;
                } else {
                    String srcValue = "";
                    if (value != null) {
                        srcValue = value.toString();
                    }
                    HashMap<String, Object> reflectMap = null;
                    if (this.FIELD_REFLECT_MAP != null) {
                        reflectMap = this.FIELD_REFLECT_MAP.get(datasetClassName
                                + "." + fieldName);
                    }
                    CellRangeAddress cra = new CellRangeAddress(index, index
                            + mergeRow - 1, col, col);
                    sheet.addMergedRegion(cra);
                    for (int rowIn = index; rowIn <= index + mergeRow - 1; rowIn++) {
                        Cell cell_1 = sheet.getRow(rowIn).createCell(col);
                        cell_1.setCellStyle(contentStyle);
                    }
                    Cell cell_1 = sheet.getRow(index).getCell(col);
                    // cell_1.setCellStyle(contentStyle);
                    if (reflectMap != null) {
                        Object textObject = fieldReflectFun(srcValue,
                                reflectMap);
                        if (textObject instanceof Double) {
                            cell_1.setCellType(Cell.CELL_TYPE_NUMERIC);
                            cell_1.setCellValue(((Double) textObject)
                                    .doubleValue());
                        } else {
                            cell_1.setCellType(Cell.CELL_TYPE_STRING);
                            cell_1.setCellValue(textObject.toString());
                        }
                    } else {
                        cell_1.setCellType(Cell.CELL_TYPE_STRING);
                        cell_1.setCellValue(srcValue);
                    }
                    col++;
                }
            }
            index += mergeRow;
        }

        return this;
    }




    /**
     * 将excel缓存写到输出流中,此处不负责关闭输出流，请在有需要的地方自行关闭
     * @param out 输出流
     * @throws ExcelException 写文件失败时抛出异常
     */
    public void write(OutputStream out) throws ExcelException {

        if (this.WORKBOOK == null || out == null ){
            return ;
        }

        try{
            this.WORKBOOK.write(out);
        }catch(IOException e){
            throw new ExcelException("Write to OutputStream fail");
        }


    }



    /**
     * 将excel缓存写到对应的文件中去,文件名称只能以.xls结束，文件不存在时将创建
     * @param filePath 要写入的文件的路径
     * @param fileName 要生成的文件的名称
     * @throws ExcelException 写文件失败时抛出异常
     */
    public void writeToFile(String filePath, String fileName) throws ExcelException {
        if ((filePath == null || "".equals(filePath.trim())) ||
                (fileName == null || "".equals(fileName.trim())) ||
                this.WORKBOOK == null) {
            return;
        }
        if(!fileName.endsWith(".xls")){
            return;
        }
        File directoty = new File(filePath);
        if(!directoty.exists()){
            directoty.mkdirs();
        }

        if (!directoty.isDirectory()) {
            directoty.delete();
            return;
        }

        if (!filePath.endsWith(File.separator)) {
            filePath += File.separator;
        }
        String fileFullName = filePath + fileName;
        File file = new File(fileFullName);
        if(!file.exists()){
            try{
                file.createNewFile();
            }catch(IOException e){
                throw new ExcelException("File "+fileFullName+" create fail! ");
            }
        }

        OutputStream fos = null;
        try{
            fos = new FileOutputStream(file);
            this.WORKBOOK.write(fos);
        }catch(Exception e){
            throw new ExcelException("Write excel to file " + fileFullName + " fail !");
        }finally {
            if(fos != null){
                try {
                    fos.flush();
                    fos.close();
                }catch(IOException e){
                    e.printStackTrace();
                }
            }
        }

    }


    /**
     * 将excel缓存通过Response输出
     * @param response
     * @param fileName
     * @throws ExcelException 写文件失败时抛出异常
     */
    public void writeToHttpResponse(HttpServletResponse response , String fileName) throws ExcelException {

        if (this.WORKBOOK == null || response == null || fileName == null || "".equals(fileName.trim())){
            return ;
        }

        // 设置响应头，控制浏览器下载该文件
        setResponseHeader(response,fileName);

        // 创建输出流
        OutputStream out = null;
        try{
            out = response.getOutputStream();
            this.WORKBOOK.write(out);
        }catch(IOException e){
            throw new ExcelException("Write excel to http response fail !");
        }finally {
            if(out != null){
                try {
                    out.flush();
                    out.close();
                }catch(IOException e){
                    e.printStackTrace();
                }
            }
        }


    }



    private  void setResponseHeader(HttpServletResponse response, String fileName) {
        try {
            try {
                fileName = new String(fileName.getBytes(),"ISO8859-1");
            } catch (UnsupportedEncodingException e) {

                e.printStackTrace();
            }
            response.setContentType("application/octet-stream;charset=ISO8859-1");
            response.setHeader("Content-Disposition", "attachment;filename="+ fileName);
            response.addHeader("Pargam", "no-cache");
            response.addHeader("Cache-Control", "no-cache");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }




    /*
     * 日期转换
     *
     * @param value
     * @param pattern
     * @return
     */
    private String formatDate(Date value) {

        String textValue = null;

        SimpleDateFormat sdf = new SimpleDateFormat(this.DATE_FORMAT);
        textValue = sdf.format(value);

        return textValue;

    }



        /*
     * 获取表格正文文本样式
     *
     * @param workbook
     * @return
     */

    private HSSFCellStyle setContentStyle() {

        // 生成并设置另一个样式
        HSSFCellStyle style2 = this.WORKBOOK.createCellStyle();
        style2.setFillForegroundColor(HSSFColor.WHITE.index);
        style2.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
        style2.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        style2.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        style2.setBorderRight(HSSFCellStyle.BORDER_THIN);
        style2.setBorderTop(HSSFCellStyle.BORDER_THIN);
        style2.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        style2.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
        // 生成另一个字体
        HSSFFont font2 = this.WORKBOOK.createFont();
        font2.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
        // 把字体应用到当前的样式
        style2.setFont(font2);
        return style2;

    }


    /*
     * 获取表格头样式
     *
     * @param workbook
     * @return
     */
    private HSSFCellStyle getHeaderStyle() {

        // 生成一个样式
        HSSFCellStyle style = this.WORKBOOK.createCellStyle();
        // 设置这些样式
        style.setFillForegroundColor(HSSFColor.GREY_25_PERCENT.index);
        style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
        style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        style.setBorderRight(HSSFCellStyle.BORDER_THIN);
        style.setBorderTop(HSSFCellStyle.BORDER_THIN);
        style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        // 生成一个字体
        HSSFFont font = this.WORKBOOK.createFont();
        font.setColor(HSSFColor.BLACK.index);
        font.setFontHeightInPoints((short) 12);
        font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        // 把字体应用到当前的样式
        style.setFont(font);
        return style;

    }






    /*
     * 获取存放T对应的class属性中所有list中存放的实例的属性名
     *
     * @param dataset 要导出的结果集
     * @return Map<String,Field[]> key是类型为list的属性名，value为list中的元素的属性
     */
    private <T> Map<String, Field[]> getListFieldMap(List<T> dataset)  throws ExcelException{

        Map<String, Field[]> listFieldMap = new HashMap<String, Field[]>();
        if (dataset == null || dataset.size() == 0) {
            return listFieldMap;
        }
        T t = dataset.iterator().next();
        Field[] fields = fieldFilterFun(t.getClass()); // 过滤之后的属性列表
        for (int i = 0; i < fields.length; i++) {
            String fieldName = fields[i].getName();
            String getMethodName = "get"
                    + fieldName.substring(0, 1).toUpperCase()
                    + fieldName.substring(1);
            Class<? extends Object> tCls = t.getClass();
            Method getMethod ;
            Object value ;
            try{
                getMethod = tCls.getMethod(getMethodName, new Class[]{});
                value = getMethod.invoke(t, new Object[]{});
            }catch(NoSuchMethodException e){
                throw new ExcelException("Method "+getMethodName+" in class "+tCls.getSimpleName()+" is missed!");
            }catch(Exception e){
                throw new ExcelException("Method "+getMethodName+" in class "+tCls.getSimpleName()+" invoked with error!");
            }

            if (value instanceof List) {
                Type gType = fields[i].getGenericType();
                ParameterizedType pType = (ParameterizedType) gType;
                String subListName = pType.getActualTypeArguments()[0]
                        .toString().replace("class ", "");
                try{
                    listFieldMap
                            .put(fieldName,
                                    fieldFilterFun(Class.forName(subListName)));
                }catch(ClassNotFoundException e){
                    throw new ExcelException("Class "+subListName+" not found !");
                }

            }
        }
        return listFieldMap;
    }

    /*
     * 属性过滤
     *
     * @param fields
     * @param filterField
     * @return
     */
    private Field[] fieldFilterFun(@SuppressWarnings("rawtypes") Class t) {
        List<Field> fieldsList = new ArrayList<Field>();
        String className = t.getSimpleName();
        Field[] sourceFields = t.getDeclaredFields();
        if (this.EXCLUDED_FIELDS == null || this.EXCLUDED_FIELDS.isEmpty()) {
            return sourceFields;
        }
        StringBuilder sb = new StringBuilder();
        for (Field field : sourceFields) {
            sb = new StringBuilder();
            sb.append(className).append(".").append(field.getName());
            if (!this.EXCLUDED_FIELDS.contains(sb.toString())) {
                fieldsList.add(field);
            }
        }
        int size = fieldsList.size();
        return fieldsList.toArray(new Field[size]);
    }

    /*
     * 配置字段映射,用于字符串类型的字段
     *
     * @param srcValue
     * @param reflectMap
     * @return
     */
    private Object fieldReflectFun(String srcValue,HashMap<String, Object> reflectMap) {
        Object result = reflectMap.get(srcValue);
        if (result == null) {
            result = reflectMap.get(this.OTHER_REFLECT_KEY);
            if (result == null) {
                return srcValue;
            } else {
                return result;
            }
        } else {
            return result;
        }
    }

    /*
     * 获取需要合并的行数,取T对象中size最大的list的长度
     */
    @SuppressWarnings("rawtypes")
    private int getMergeRow(Object t) throws ExcelException {

        // 利用反射，根据javabean属性的先后顺序，动态调用getXxx()方法得到属性值
        Field[] fields = fieldFilterFun(t.getClass());
        int mergeRowNum = 1;
        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i];
            String fieldName = field.getName();
            String getMethodName = "get"
                    + fieldName.substring(0, 1).toUpperCase()
                    + fieldName.substring(1);

            Class<? extends Object> tCls = t.getClass();
            Method getMethod ;
            Object value ;
            try{
                getMethod = tCls.getMethod(getMethodName, new Class[]{});
                value = getMethod.invoke(t, new Object[]{});
            }catch(NoSuchMethodException e){
                throw new ExcelException("Method "+getMethodName+" in class "+tCls.getSimpleName()+" is missed!");
            }catch(Exception e){
                throw new ExcelException("Method "+getMethodName+" in class "+tCls.getSimpleName()+" invoked with error!");
            }
            if (value instanceof List) {
                List subList = (List) value;
                int len = subList.size();
                if (len > mergeRowNum) {
                    mergeRowNum = len;
                }

            }

        }

        return mergeRowNum;
    }













    /**
     * excel工作表实体
     */
    private HSSFWorkbook WORKBOOK;

    /**
     * 属性值映射转换表
     */
    private Map<String, HashMap<String, Object>> FIELD_REFLECT_MAP;

    /**
     * 不导出的列
     */
    private HashSet<String> EXCLUDED_FIELDS;

    /**
     * 列名称数组
     */
    private String[] HEADERS ;

    /**
     * sheet页名称
     */
    private String SHEET_TITLE = "sheet1";

    /**
     * 列宽度，单位px
     */
    private int COLUMN_WIDTH = 15;

    /**
     * 日期类型数据转换格式
     */
    private String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";

    /**
     * 起始行
     */
    private int START_ROW = 0;

    /**
     * 起始列
     */
    private int START_COLUMN = 0;


    /**
     * 在配置字段映射时如果没有映射类型,则采用这个字段对应的映射值
     */
    public static final String OTHER_REFLECT_KEY = "other";

    /*
     * 限制可定义最小列宽
     */
    private static final int SMALLEST_COLUMN_WIDTH = 5;

    /*
     * 限制可定义最大列宽
     */
    private static final int BIGGEST_COLUMN_WIDTH = 500;


}
